package org.github.xhjcehust.dubbo.proxy.util;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;

public class HttpClientUtil {
	private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
	

	
	/**
	 * GET请求
	 * 
	 * @param url
	 * @param isHttps
	 * @return
	 */
	public static String httpGet(String url, boolean isHttps) {
		logger.info("httpGet start, url : {}, isHttps : {}", url, isHttps);
		if(!isConnect(url)){
			return "";
		}
		final HttpGet get = new HttpGet(url);
		get.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));

		RequestConfig requestConfig = RequestConfig.custom()
		        .setConnectTimeout(2000)//设置连接超时时间，单位毫秒
		        .setConnectionRequestTimeout(1000)//设置从connect Manager获取Connection 超时时间
		        .setSocketTimeout(5000).build();//请求获取数据的超时时间
		get.setConfig(requestConfig);
		CloseableHttpClient httpClient = getHttpClient(isHttps);
		CloseableHttpResponse httpResponse = null;
		StringBuilder resultSb = new StringBuilder();
		try {
			httpResponse = httpClient.execute(get);
			final HttpEntity resultEntity = httpResponse.getEntity();
			if (null != resultEntity) {
				String line;
				BufferedReader bufferedReader;
				InputStreamReader streamReader = null;

				streamReader = new InputStreamReader(resultEntity.getContent(), "UTF-8");

				if (streamReader != null) {
					bufferedReader = new BufferedReader(streamReader);
					while ((line = bufferedReader.readLine()) != null) {
						resultSb.append(line);
					}
					streamReader.close();
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (httpResponse != null) {
				try {
					httpResponse.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		logger.info("httpGet end, result : {}", resultSb.toString());
		return resultSb.toString();
	}

	/**
	 * GET请求
	 *
	 * @param url
	 * @param isHttps
	 * @return
	 */
	public static String httpGet(String url, String token, boolean isHttps) {
		logger.info("httpGet start, url : {}, isHttps : {}", url, isHttps);
		final HttpGet get = new HttpGet(url);
		get.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
		get.setHeader(new BasicHeader("Token", token));

		RequestConfig requestConfig = RequestConfig.custom()
		        .setConnectTimeout(2000)//设置连接超时时间，单位毫秒
		        .setConnectionRequestTimeout(1000)//设置从connect Manager获取Connection 超时时间
		        .setSocketTimeout(5000).build();//请求获取数据的超时时间
		get.setConfig(requestConfig);
		CloseableHttpClient httpClient = getHttpClient(isHttps);
		CloseableHttpResponse httpResponse = null;
		StringBuilder resultSb = new StringBuilder();
		try {
			httpResponse = httpClient.execute(get);
			final HttpEntity resultEntity = httpResponse.getEntity();
			if (null != resultEntity) {
				String line;
				BufferedReader bufferedReader;
				InputStreamReader streamReader = null;

				streamReader = new InputStreamReader(resultEntity.getContent(), "UTF-8");

				if (streamReader != null) {
					bufferedReader = new BufferedReader(streamReader);
					while ((line = bufferedReader.readLine()) != null) {
						resultSb.append(line);
					}
					streamReader.close();
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (httpResponse != null) {
				try {
					httpResponse.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		logger.info("httpGet end, result : {}", resultSb.toString());
		return resultSb.toString();
	}
	
	/**
	 * 获取httpcient
	 * 
	 * @param isHttps
	 * @return
	 */
	public static CloseableHttpClient getHttpClient(boolean isHttps) {

		if (!isHttps) {
			CloseableHttpClient httpClient = HttpClients.createDefault();
			return httpClient;
		}

		SSLContext ctx = null;
		try {
			ctx = SSLContext.getInstance("TLS");
			X509TrustManager tm = new X509TrustManager() {
				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}

				public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
				}

				public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
				}
			};
			ctx.init(null, new TrustManager[] { tm }, null);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		SSLConnectionSocketFactory ssf = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);
		CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(ssf).build();
		return httpClient;
	}
	
	public static boolean isConnect(String url){
		HttpURLConnection conn;
		try {
			 URL targetUrl=new URL(url);
			 conn = (HttpURLConnection)targetUrl.openConnection();
			 int code=conn.getResponseCode();
			 //logger.error("HttpClientUtil::isConnect:code is "+code);
			 if(HttpURLConnection.HTTP_OK==code){
			    return true;
			 }
			   
		 } catch (IOException e) {
			 logger.error("HttpClientUtil::isConnect:"+e);
		 }
		 return false;
	}

	public static String post(String urlString, Map<String, String> postHeaders ,String jsonParam){
		CloseableHttpClient httpclient = HttpClientBuilder.create().build();
		HttpPost post = new HttpPost(urlString);
		for (String pKey : postHeaders.keySet()) {
			post.setHeader(pKey, postHeaders.get(pKey));
		}
		RequestConfig requestConfig = RequestConfig.custom()
				.setConnectTimeout(60000)
				.setConnectionRequestTimeout(60000)
				.setSocketTimeout(60000)
				.build();
		post.setConfig(requestConfig);
		String result = null;
		try {
			StringEntity s = new StringEntity(jsonParam,"UTF-8");
			s.setContentType("application/json");//发送json数据需要设置contentType
			post.setEntity(s);
			HttpResponse res = httpclient.execute(post);
			if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
				result = EntityUtils.toString(res.getEntity());// 返回json格式：
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return result;
	}

	/*
	 * http远程访问SOAP协议接口
	 * @param url： 服务接口地址"http://192.168.0.120:8222/HelloWorld?wsdl"
	 * @param isClass：接口类名
	 * @param isMethod： 接口方法名
	 * @param sendSoapString： soap协议xml格式访问接口
	 * @return  soap协议xml格式
	 * @备注：有四种请求头格式1、SOAP 1.1； 2、SOAP 1.2 ； 3、HTTP GET； 4、HTTP POST
	 * 参考---》http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?op=getWeatherbyCityName
	 */
	public static String sendWebService(String url,String isClass,String isMethod,StringBuffer paramsXml,String token) throws Exception {
		//传过来的xml格式
		String xml = paramsXml.toString();
		if (xml==null){
			return "传入xml参数不能为空！";
		}
		URL sopul = new URL(url);
		//获取连接
		URLConnection connention = sopul.openConnection();
		//缓存设置
		connention.setUseCaches(false);
		//设置输入输出，新创建的connection默认是没有读写权限的
		connention.setDoInput(true);
		connention.setDoOutput(true);
		//设置请求头
		connention.setRequestProperty("Content-Length",xml.length()+"");
		//这里设置请求头类型为xml,传统http请求的是超文本传输格式text/html
		connention.setRequestProperty("Content-Type","text/xml; charset=utf-8");
		//调用的类名，方法名
		connention.setRequestProperty(isClass,isMethod);
		//这里如果携带token设置token,没传则不设置
		if (token!=null){
			connention.setRequestProperty("Authorization","Bearer "+token);
		}
		OutputStream os = connention.getOutputStream();
		OutputStreamWriter osw = new OutputStreamWriter(os,"utf-8");
		//写入传过来的xml文件格式
		osw.write(xml);
		//释放资源
		osw.flush();
		osw.close();
		//下面获取webservice返回过来的流
		InputStream is = connention.getInputStream();
		if (is!=null){
			byte[] bytes = new byte[0];
			bytes=new byte[is.available()];
			is.read(bytes);
			//将字节数组转换为字符串输出
			String outXml = new String(bytes,"UTF-8");
			return outXml;
		}
		return null;
	}

	/**
	 * POST请求
	 *
	 * @param url
	 * @param postHeaders
	 * @param postEntity
	 * @throws Exception
	 * @return 提取HTTP响应报文包体，以字符串形式返回
	 */
	public static String httpPost(final String url, final Map<String, String> postHeaders, final String postEntity) throws Exception {

		final URL postURL = new URL(url);
		final HttpURLConnection connection = (HttpURLConnection) postURL.openConnection();
		connection.setDoOutput(true);
		connection.setDoInput(true);
		connection.setRequestMethod("POST");
		connection.setUseCaches(false);
		connection.setConnectTimeout(60000);
		connection.setReadTimeout(20000);
		if (null != postHeaders) {
			for (final String pKey : postHeaders.keySet()) {
				connection.setRequestProperty(pKey, postHeaders.get(pKey));
			}
		}
		connection.connect();

		if (null != postEntity) {
			final DataOutputStream out = new DataOutputStream(connection.getOutputStream());
			out.write(postEntity.getBytes());
			out.flush();
			out.close(); // flush and close
		}
		final int responseCode = connection.getResponseCode();
		if (responseCode == HttpURLConnection.HTTP_OK) {

			final InputStream inStream = connection.getInputStream();

			final BufferedReader in = new BufferedReader(new InputStreamReader(inStream, "utf-8"));
			final StringBuffer buffer = new StringBuffer();
			int ch;
			while ((ch = in.read()) > -1) {
				buffer.append((char) ch);
			}

			/* 解析完毕关闭输入流 */
			in.close();
			/* 关闭URL连接 */
			if (connection != null) {
				connection.disconnect();
			}

			return buffer.toString();

		} else {
			throw new RuntimeException("Bad response status, " + responseCode);
		}
	}

}
